#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define MAXLINE 4096
#define SERV_PORT 8080 // 服务器端口，请根据实际情况调整

int main(int argc, char **argv)
{
    // 检查命令行参数
    if (argc != 2)
    {
        fprintf(stderr, "usage: udpclient <IPaddress> ");
        exit(EXIT_FAILURE);
    }

    int socket_fd;
    if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr)); // 清空结构体
    server_addr.sin_family = AF_INET;             // 使用 IPv4
    server_addr.sin_port = htons(SERV_PORT);      // 设置服务器端口
    if (inet_pton(AF_INET, argv[1], &server_addr.sin_addr) <= 0)
    {
        fprintf(stderr, "Invalid address/ Address not supported ");
        exit(EXIT_FAILURE);
    }

    socklen_t server_len = sizeof(server_addr);

    // 使用 malloc 分配 memory for reply address, 这是为了接收响应
    struct sockaddr *reply_addr = malloc(server_len);
    if (reply_addr == NULL)
    {
        perror("malloc failed");
        close(socket_fd);
        exit(EXIT_FAILURE);
    }

    char send_line[MAXLINE], recv_line[MAXLINE + 1];
    socklen_t len;
    int n;

    // 循环读取用户输入并发送
    printf("Enter message (type 'exit' to quit): ");
    while (fgets(send_line, MAXLINE, stdin) != NULL)
    {
        // 去掉输入行末尾的换行符
        size_t i = strlen(send_line);
        if (i > 0 && send_line[i - 1] == '\n')
        {
            send_line[i - 1] = '\0'; // 替换换行符为字符串结束符
        }

        if (strcmp(send_line, "exit") == 0)
        {
            printf("Exiting...  ");
            break; // 用户输入 'exit'，结束循环
        }

        printf("Now sending: %s ", send_line);
        ssize_t rt = sendto(socket_fd, send_line, strlen(send_line), 0,
                            (struct sockaddr *)&server_addr, server_len);
        if (rt < 0)
        {
            perror("send failed");
            continue; // 发送失败，继续下一个循环
        }
        printf("Sent bytes: %zu ", rt);

        len = 0;
        n = recvfrom(socket_fd, recv_line, MAXLINE, 0, reply_addr, &len);
        if (n < 0)
        {
            perror("recvfrom failed");
            continue; // 如果接收失败，继续下一个循环
        }
        recv_line[n] = 0; // 终止字符串
        fputs("Received: ", stdout);
        fputs(recv_line, stdout);
        fputs(" ", stdout);
    }

    // 清理资源
    free(reply_addr);
    close(socket_fd);
    return 0;
}